package net.portly.cst.loader;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;

import net.portly.cst.StructuralAssetInstance;
import net.portly.cst.flex.FlexAssetAttribute;

import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.fatwire.rest.beans.AssetBean;
import com.fatwire.rest.beans.Attribute;
import com.fatwire.rest.beans.Attribute.Data;
import com.fatwire.rest.beans.List;
import com.fatwire.rest.beans.Struct;

public class StructuralAssetLoader extends SimpleLoader {

	private String idPattern = null;
	private java.util.List<FlexAssetAttribute> flexAssetAttributes;
	private JAXBContext context;
	private Unmarshaller um;

	public StructuralAssetLoader() {
		super();
		pattern = "//assetBean/*";
		idPattern = "//attribute/name[text()='id']/../data/longValue/text()[1]";
		init();
		//attributesPattern = "//attribute/name[text()='Groups' or text()='Attributes']/../data/listValue/item";
	}

	
	private void init() {
		try {
			context = JAXBContext.newInstance(AssetBean.class);
			um = context.createUnmarshaller();
		} catch (JAXBException e) {
			e.printStackTrace();
		}
	}


	@Override
	public void loadAttributes(net.portly.cst.CSTDocument cstDoc) {
		File file = new File(cstDoc.getFileName());
		try {
			AssetBean ns2 = (AssetBean)um.unmarshal(file);

			getMetaData().put("createdby", ns2.getCreatedby());
			getMetaData().put("createddate", getDateFormat(ns2.getCreateddate()));
			getMetaData().put("description", ns2.getDescription());
			getMetaData().put("id", ns2.getId());
			getMetaData().put("name", ns2.getName());
			getMetaData().put("status", ns2.getStatus());
			getMetaData().put("subtype", ns2.getSubtype());

			for (Attribute attribute : ns2.getAttributes()) {
				if ("Attributes".equals(attribute.getName())) {
					flexAssetAttributes = new ArrayList<FlexAssetAttribute>();
					
					Data ad = attribute.getData();
					List lv = ad.getListValue();
					
					for (Struct item : lv.getItems()) {
						flexAssetAttributes.add(new FlexAssetAttribute(item));
					}
				} else {
					seekOutInterestingMetaData(attribute.getName(), attribute.getData());
					if ("type".equals(attribute.getName())){
						getMetaData().put("type", attribute.getData().getStringValue());
					}
				}
			}
		} catch (JAXBException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private void seekOutInterestingMetaData(String name, Data data) {
		String meta[] = new String []{"fw_uid", "type", "assettypename"};
		
		for (int counter = 0; name != null && data != null && counter < meta.length; counter++) {
			if (meta[counter].equals(name)){
				getMetaData().put(meta[counter], data.getStringValue());
			}
		}
	}

	private String getDateFormat(Date date) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
		return sdf.format(date);
	}
	
	protected void applyAttributeAttributes(NodeList nl) {
		if (nl != null && nl.getLength() > 0 && nl.item(0).getFirstChild() != null) {
			for (int counter = 0; counter < nl.getLength(); counter++) {
				Node nlItem = nl.item(counter);
				if (nlItem != null && nlItem.getNodeType() == Node.ELEMENT_NODE) {
					String content = nlItem.getTextContent();
					System.out.println("Content for : " + nlItem.getNodeName() + " : " + content);
				}
			}
		}
	}

	@Override
	protected void metaDataFilter(Node node, String content) {
		// * attribute data not required for a FlexDef
		if (!"attribute".equals(node.getNodeName())) {
			getMetaData().put(node.getNodeName(), content);
		} else {
			XPathExpression expr = null;

			if (getMetaData().get("id") == null) {
				try {
					expr = xpath.compile(idPattern);
					NodeList idList = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);

					if (idList != null) {
						getMetaData().put("id", idList.item(0).getTextContent());
					}
				} catch (XPathExpressionException e) {
					e.printStackTrace();
				}
			}
		}
	}

	public StructuralAssetInstance getStructuralAssetInstance() {
		return new StructuralAssetInstance(getMetaData(), flexAssetAttributes);
	}
}
